//
//  LBToneCurveFilter.mm
//  OpenGLGame
//
//  Created by Nguyen Cong Huy on 11/28/12.
//  Copyright (c) 2013 UIT. All rights reserved.
//

#include <iostream>
#include "LBToneCurveFilter.h"
#include "LBGraphics.h"
#include "LBTexture.h"
#include "LBFramebuffer.h"
#include "Matrix.h"
#include "LBUtils.h"
#include "Utils.h"

char toneCurveVerShaderStr[] = ""
"precision mediump float;"
"attribute highp vec4 position;"
"attribute highp vec4 texCoor;"
"uniform highp mat4 mWorld;"
"uniform highp mat4 mProjection;"

"varying vec2 vtexCoor;"
"varying highp vec4 vposition;"

"void main()"
"{"
"    gl_Position = mProjection * mWorld * position;"
"    vtexCoor = texCoor.xy;"
"    vposition = gl_Position;"
"}";

char toneCurveFragShaderStr[] = ""
"precision mediump float;"

"varying vec2 vtexCoor;"

"uniform sampler2D texture;"
"uniform sampler2D curveTexture; "

"void main()"
"{"
"    lowp vec4 textureColor = texture2D(texture, vtexCoor);"
"   lowp float redCurveValue = texture2D(curveTexture, vec2(textureColor.r, 0.0)).r;"
"   lowp float greenCurveValue = texture2D(curveTexture, vec2(textureColor.g, 0.0)).g;"
"   lowp float blueCurveValue = texture2D(curveTexture, vec2(textureColor.b, 0.0)).b;"
"    gl_FragColor = vec4(redCurveValue, greenCurveValue, blueCurveValue, textureColor.a);"

//"    lowp vec4 textureColor = texture2D(curveTexture, vec2(0.5, 0.0));"
//"    gl_FragColor = textureColor;"
"}";

LBToneCurveFilter::LBToneCurveFilter(){
    LBFilter::init(toneCurveVerShaderStr, toneCurveFragShaderStr);
    LBGraphics::getInstance()->useProgram(program);
    curveTextureUniform = program->uniformIndex("curveTexture");
    toneCurveTexture = 0;
}

void LBToneCurveFilter::renderTexture(int x, int y, float scaleX, float scaleY){
    LBGraphics* g = LBGraphics::getInstance();
    texture->setLocationAndScale(x, y, scaleX, scaleY);
    texture->setAngle(0);
    texture->calculateMatrix();
    
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture->getTexId());
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    //glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    
    glUniform1i(textureUniform, 0);
    glVertexAttribPointer(positionAttribute, 2, GL_FLOAT, GL_FALSE, 0, texture->getImageVertices());
    glVertexAttribPointer(texCoorAttribute, 2, GL_FLOAT, GL_FALSE, 0, texture->getTexCoors());
    glUniformMatrix4fv(mWorldUniform, 1, GL_FALSE, &(texture->getWorldMatrix()->m[0][0]));
    glUniformMatrix4fv(mProjectionUniform, 1, GL_FALSE, &(g->getProjectionMatrix()->m[0][0]));
    
    
    
    glActiveTexture(GL_TEXTURE1);
    if(toneCurveTexture != 0){
        glBindTexture(GL_TEXTURE_2D, toneCurveTexture);	
        glUniform1i(curveTextureUniform, 1);
    }
    
    glEnableVertexAttribArray(positionAttribute);
    glEnableVertexAttribArray(texCoorAttribute);
    
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    
}

void LBToneCurveFilter::setCurveImageData(unsigned char* toneCurveByteArray){
    if (!toneCurveTexture)
    {
        glActiveTexture(GL_TEXTURE1);
        glGenTextures(1, &toneCurveTexture);
        glBindTexture(GL_TEXTURE_2D, toneCurveTexture);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    }
    else
    {
        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D, toneCurveTexture);
    }
    
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256 /*width*/, 1 /*height*/, 0, GL_BGRA, GL_UNSIGNED_BYTE, toneCurveByteArray);
}